using System.Linq;
using System;
using System.Collections.Generic;
using System.Text;
using ResearchId.Properties;

namespace ResearchId
{
    public class ClaimView
    {        
        public int ClaimId { get; set; }
        public string ClaimName {get;set;}
        public string ClaimUrl {get;set;}
        public string DataType { get; set; }
    }
    partial class ResearchIdDataContext
    {   
#if DEBUG
        public ResearchIdDataContext() : this(Settings.Default.ConnectionString_local) { }
#else
        public ResearchIdDataContext() : this(Settings.Default.ConnectionString) { }
#endif
    }
    public partial class Group
    {
        public static ResearchIdDataContext db = new ResearchIdDataContext();
        public static List<Group> GetGroups()
        {
            var Results = from x in db.Groups
                          orderby x.GroupName
                          select x;
            return Results.ToList();
        }
        public static Group GetGroup(int GroupId)
        {
            Group myGroup = db.Groups.Single(x => x.GroupId == GroupId);
            return myGroup;
        }
        public string ClaimListString
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                foreach (GroupClaim myGroupClaim in this.GroupClaims)
                {
                    sb.Append(myGroupClaim.Claim.ClaimName + ", ");
                }
                return sb.Remove(sb.Length - 2, 2).ToString();
            }
        }
    }
    public class IndividualClaimsView
    {
        public int IndividualId {get; set;}
        public int ClaimId {get; set;}
        public string ClaimName { get; set; }
        public string Value { get; set; }
    }
    public enum ClaimEnum { Gender = 1, Birthdate = 2, Address = 3, City = 4, State = 5, ZipCode = 6, Country = 7, GivenName = 8, Surname = 10, EmailAddress = 11,StudentId=12 };
    public partial class IndividualClaim
    {       
        public static void CreateIndividualClaim(int IndividualId, ClaimEnum ClaimToCreate, string Value, string DataType)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            bool Insert = false;
            IndividualClaim ic = IndividualClaim.GetIndividualClaim(ClaimToCreate, IndividualId);
            if (ic == null)
            {
                ic = new IndividualClaim();
                Insert = true;
            }
            ic.IndividualId = IndividualId;
            ic.IsValidated = false;
            ic.Value = Value;
            ic.DataType = DataType;
            ic.ClaimId = (int)ClaimToCreate;
            if (Insert)
            {
                db.IndividualClaims.InsertOnSubmit(ic);
            }
            db.SubmitChanges();
        }
        public static void CreateIndividualClaim(string UserName, ClaimEnum ClaimToCreate, string Value, string DataType)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            bool Insert = false;
            Individual i = Individual.GetIndividual(UserName);
            CreateIndividualClaim(i.IndividualId, ClaimToCreate, Value, DataType);
        }
        public static IndividualClaim GetIndividualClaim(ClaimEnum ClaimToSelect, int IndividualId)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            IndividualClaim ic = db.IndividualClaims.SingleOrDefault(x => x.ClaimId == (int)ClaimToSelect & x.IndividualId == IndividualId);
            return ic;
        }        
        public static void DeleteIndividualClaim(int IndividualId, ClaimEnum ClaimToDelete)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            IndividualClaim ic = db.IndividualClaims.SingleOrDefault(x => x.IndividualId == IndividualId & x.ClaimId == (int)ClaimToDelete);
            if (ic != null)
            {
                db.IndividualClaims.DeleteOnSubmit(ic);
                db.SubmitChanges();
            }
        }
    }
    public partial class Individual
    {
        public List<IndividualClaimsView> GetIndividualClaims()
        {
            var Results = from x in db.IndividualClaims
                          where x.IndividualId == this.IndividualId
                          join y in db.Claims on x.ClaimId equals y.ClaimId
                          select new IndividualClaimsView{
                              IndividualId = x.IndividualId
                              ,ClaimId = y.ClaimId
                              , ClaimName = y.ClaimName
                              ,Value = x.Value };
            return Results.ToList();
        }
        public List<IndividualClaimsView> GetIndividualClaims(int[] ClaimIds)
        {
            var Results = from x in db.IndividualClaims
                          where x.IndividualId == this.IndividualId
                          & ClaimIds.Contains(x.ClaimId)
                          join y in db.Claims on x.ClaimId equals y.ClaimId
                          select new IndividualClaimsView
                          {
                              IndividualId = x.IndividualId
                              ,
                              ClaimId = y.ClaimId
                              ,
                              ClaimName = y.ClaimName
                              ,
                              Value = x.Value
                          };
            return Results.ToList();
        }
        public static ResearchIdDataContext db = new ResearchIdDataContext();
        public static Individual CreateIndividual(string LoginName,string password)
        {
            if (UserNameExists(LoginName))
            {
                throw new Exception("Username already exists. Please choose another.");
            }
            Individual i = new Individual();
            i.LoginName = LoginName;
            i.PasswordDecrypted = password;
            db.Individuals.InsertOnSubmit(i);
            db.SubmitChanges();
            return i;
        }
        public static bool UserNameExists(string LoginName)
        {
            int Count = db.Individuals.Count(x => x.LoginName == LoginName);
            if (Count == 0)
                return false;
            else
                return true;
        }
        public static Individual GetIndividual(string LoginName)
        {            
            Individual i = db.Individuals.SingleOrDefault(p => p.LoginName == LoginName);
            return i;
        }
        public static bool AuthenticateUser(string UserName, string Password)
        {
            Individual p = Individual.GetIndividual(UserName);            
            if (p != null && p.PasswordDecrypted == Password)
            {                
                return true;
            }
            else
            {
                return false;
            }
        }
        public string PasswordDecrypted
        {
            get
            {
                return Utility.RijndaelSimple.Decrypt(
                    this.Password
                    , Properties.Settings.Default.Encryption_Passphrase
                    , Properties.Settings.Default.Encryption_Salt
                    , Properties.Settings.Default.Encryption_HashAlgorithm
                    , Properties.Settings.Default.Encryption_PasswordIterations
                    , Properties.Settings.Default.Encryption_InitVector
                    , Properties.Settings.Default.Encryption_KeySize);
            }
            set
            {
                Password = Utility.RijndaelSimple.Encrypt(
                    value
                    , Properties.Settings.Default.Encryption_Passphrase
                    , Properties.Settings.Default.Encryption_Salt
                    , Properties.Settings.Default.Encryption_HashAlgorithm
                    , Properties.Settings.Default.Encryption_PasswordIterations
                    , Properties.Settings.Default.Encryption_InitVector
                    , Properties.Settings.Default.Encryption_KeySize);
            }
        }
        
    }
    public partial class Country
    {
        public static List<Country> GetCountry()
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            List<Country> Countries = (from c in db.Countries
                                       orderby c.CountryName
                                       select c).ToList();
            return Countries;
        }
        public static int GetUsaCountryId
        {
            get { return 612; }
        }
    }
    public partial class Province
    {
        public static List<Province> GetProvince(int CountryId)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            List<Province> Provinces = (from p in db.Provinces
                                        where p.CountryId == CountryId
                                        orderby p.Name
                                        select p).ToList();
            return Provinces;
                                        
        }
    }
    public partial class IndividualEmail
    {
        public static void AddEmail(string EmailAddress, int IndividualId)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            IndividualEmail ie = new IndividualEmail();
            ie.ValidationCode = RandomPassword.Generate(8);
            ie.EmailAddress = EmailAddress;
            ie.IndividualId = IndividualId;
            ie.IsValidated = false;
            ie.IsPrimary = false;
            db.IndividualEmails.InsertOnSubmit(ie);            
            db.SubmitChanges();
        }
        public static void DeleteEmail(string EmailAddress, int IndividualId)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            IndividualEmail id = db.IndividualEmails.SingleOrDefault(
                x => x.IndividualId == IndividualId & x.EmailAddress == EmailAddress);
            bool IsPrimary = id.IsPrimary;            
            db.IndividualEmails.DeleteOnSubmit(id);
            db.SubmitChanges();
            if (IsPrimary == true)
            {
                IndividualClaim.DeleteIndividualClaim(IndividualId, ClaimEnum.EmailAddress);
                //Find another email to promote
                IndividualEmail ToPromote = (from x in db.IndividualEmails
                                             where x.EmailAddress != EmailAddress
                                             & x.IsValidated == true
                                             select x).FirstOrDefault();
                if (ToPromote != null)
                {
                    IndividualEmail.MakePrimary(ToPromote.EmailAddress, IndividualId);
                }
            }
        }
        public static bool Validate(string EmailAddress, int IndividualId, string ValidationCode)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            IndividualEmail ie = db.IndividualEmails.SingleOrDefault(x => x.EmailAddress == EmailAddress
                & x.IndividualId == IndividualId
                & x.ValidationCode == ValidationCode);
            if (ie == null)
            {
                return false;
            }
            else
            {
                ie.IsValidated = true;                
                db.SubmitChanges();
                if (db.IndividualEmails.Count(
                    x => x.IndividualId == IndividualId
                        & x.IsPrimary == true) == 0)
                {
                    MakePrimary(EmailAddress, IndividualId);
                }
                return true;
            }                                                                                  
        }
        public static void MakePrimary(string EmailAddress, int IndividualId)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            // Turn everything else to not be primary
            List<IndividualEmail> list = (from x in db.IndividualEmails
                                          where x.IndividualId == IndividualId
                                          select x).ToList();
            foreach (IndividualEmail ie in list)
            {
                ie.IsPrimary = false;
            }            
            // Set single email value
            IndividualEmail myIe = (from x in list where x.EmailAddress == EmailAddress select x).Single();
            myIe.IsPrimary = true;
            db.SubmitChanges();
            // Set claim value
            IndividualClaim.CreateIndividualClaim(IndividualId,
                ClaimEnum.EmailAddress
                ,EmailAddress
                ,"System.String");            
        }
        public static List<IndividualEmail> GetIndividualEmail(int IndividualId)
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            List<IndividualEmail> list = (from x in db.IndividualEmails
                                          where x.IndividualId == IndividualId
                                          orderby x.EmailAddress
                                          select x).ToList();
            return list;
        }
    }
    public partial class Claim
    {
        public static List<Claim> GetClaim()
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            return (from x in db.Claims
                    orderby x.ClaimName
                    select x).ToList();
        }
        public static List<ClaimView> GetClaimView()
        {
            ResearchIdDataContext db = new ResearchIdDataContext();
            return (from x in db.Claims
                    orderby x.ClaimName
                    select new ClaimView { 
                        ClaimId = x.ClaimId
                        , ClaimName = x.ClaimName
                        , ClaimUrl = x.ClaimUrl
                        , DataType = x.DataType}
                        ).ToList();
        }
    }
}
